package com.small.nacos.naming.misc;

import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.common.utils.ClassUtils;
import com.small.nacos.SmallNacosApplication;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Author zhoujin
 * @Date 2022/7/23 12:38
 */
public class GlobalExecutor {

    private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors() <= 1 ? 1 : Runtime.getRuntime().availableProcessors() / 2;

    private static final String GROUP_NAME = "com.small.nacos.naming";

    private static final ScheduledExecutorService NAMING_HEALTH_EXECUTOR = ExecutorFactory.Managed
            .newScheduledExecutorService(GROUP_NAME,
                    Integer.max(Integer.getInteger("com.small.nacos.naming.health.thread.num", DEFAULT_THREAD_COUNT),
                            1), new NameThreadFactory("com.small.nacos.naming.health"));

    private static final ScheduledExecutorService DISTRO_NOTIFY_EXECUTOR = ExecutorFactory.Managed
            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(SmallNacosApplication.class),
                    new NameThreadFactory("com.alibaba.nacos.naming.distro.notifier"));

    private static final ScheduledExecutorService UDP_SENDER_EXECUTOR = ExecutorFactory.Managed
            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(SmallNacosApplication.class),
                    new NameThreadFactory("com.alibaba.nacos.naming.push.udpSender"));

    private static final ScheduledExecutorService RETRANSMITTER_EXECUTOR = ExecutorFactory.Managed
            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(SmallNacosApplication.class),
                    new NameThreadFactory("com.alibaba.nacos.naming.push.retransmitter"));

    public static ScheduledFuture<?> scheduleNamingHealth(Runnable command, long initialDelay, long delay,
                                                          TimeUnit unit) {
        return NAMING_HEALTH_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);
    }

    public static ScheduledFuture<?> scheduleNamingHealth(Runnable command, long delay, TimeUnit unit) {
        return NAMING_HEALTH_EXECUTOR.schedule(command, delay, unit);
    }

    public static void submitDistroNotifyTask(Runnable runnable) {
        DISTRO_NOTIFY_EXECUTOR.submit(runnable);
    }


    public static ScheduledFuture<?> scheduleUdpSender(Runnable runnable, long delay, TimeUnit unit) {
        return UDP_SENDER_EXECUTOR.schedule(runnable, delay, unit);
    }

    public static void scheduleRetransmitter(Runnable runnable, long delay, TimeUnit unit) {
        RETRANSMITTER_EXECUTOR.schedule(runnable, delay, unit);
    }
}
